home *** CD-ROM | disk | FTP | other *** search
/ No Fragments Archive 12: Textmags & Docs / nf_archive_12.iso / MAGS / SOURCES / ATARI_SRC.ZIP / atari source / HDX_BACK / HDX401.ATB / BSL.C < prev    next >
Encoding:
C/C++ Source or Header  |  2001-02-09  |  21.5 KB  |  776 lines

  1.  /*
  2.  * BSL.C
  3.  *
  4.  *     Functions to manipulate the Bad Sector List.
  5.  *
  6.  * 25-Nov-87    ml.    Started this mess.
  7.  * 04-Dec-87    ml.    Hmmm, looks OK.
  8.  * 11-Dec-87    ml.    Added bsl2fat().
  9.  * 14-Dec-87    ml.    Structure of BSL is changed (_again_!).
  10.  *            Now, first entry in BSL contains number VENDOR
  11.  *            entries.  First byte of 2nd entry is the checksum
  12.  *            byte, while 2nd and 3rd bytes are reserved for 
  13.  *            future use.
  14.  * 08-Nov-87    jye. change or add codes so that can be used for MS-DOS
  15.  *
  16.  */
  17.  
  18. #include "obdefs.h"
  19. #include "osbind.h"
  20. #include "mydefs.h"
  21. #include "part.h"
  22. #include "bsl.h" 
  23. #include "hdx.h"
  24. #include "addr.h" 
  25. #include "myerror.h" 
  26.  
  27. /* Globals */
  28. BYTE *bsl;            /* bad sector list */
  29. long bslsiz;            /* num sectors BSL occupies */
  30. SECTOR badbuf[WARNBADSECTS];    /* bad sectors buffer */
  31. extern int tformat;        /* 1: called by Format */
  32. extern long ratio;
  33.  
  34.  
  35. /*
  36.  *  Get size of the Bad Sector List (in sectors)
  37.  *    Input:
  38.  *        pdev - physical unit BSL belongs to.
  39.  *    Return:
  40.  *        number of sectors BSL occupies.
  41.  */
  42. long 
  43. gbslsiz(pdev) 
  44. int pdev;    /* physical device number */
  45. {
  46.     char bs[512];    /* boot sector image */
  47.     UWORD  ret;
  48.     
  49.        if ((ret = getroot(pdev, bs, (SECTOR)0)) != 0) {
  50.            if (tsterr(ret) == OK)
  51.             return MDMERR;
  52.         else return ERROR;
  53.        }
  54.        if (((RSECT *)(bs + 0x200 - sizeof(RSECT)))->bsl_st != STBSL)
  55.            return 0L;
  56.        return(((RSECT *)(bs + 0x200 - sizeof(RSECT)))->bsl_cnt);
  57. }
  58.  
  59.  
  60. /*
  61.  *  Set BSL parameters (starting sector and size of BSL) into
  62.  *  root sector image.
  63.  *    Input:
  64.  *        image - root sector image.
  65.  */
  66.  
  67. sbslparm(image)
  68. char *image;
  69. {
  70.     ((RSECT *)(image + 0x200 - sizeof(RSECT)))->bsl_st = STBSL;
  71.     ((RSECT *)(image + 0x200 - sizeof(RSECT)))->bsl_cnt = bslsiz;
  72. }
  73.  
  74.  
  75. /* 
  76.  *  Create a BSL in memory.
  77.  *    Input:
  78.  *        pdev - physical unit BSL will belong to.
  79.  *        type - kind of BSL to be created. NEW or EXPAND.
  80.  *        nents - number of VENDOR entries BSL should hold.
  81.  *    Output:
  82.  *        bsl - pointer to the BSL. (in bsl.h)
  83.  *    Return:
  84.  *        OK - everything is fine.
  85.  *        ERROR - anything is wrong.
  86.  *    Comment:
  87.  *        "NEW" means to create a totally new BSL.
  88.  *        "EXPAND" means to expand an existing BSL.
  89.  */
  90. creabsl(pdev, type, nents)
  91. int  pdev;    /* physical unit number */
  92. int  type;    /* kind of BSL to be created */
  93. long  nents;    /* num VENDOR entries in BSL */
  94. {
  95.     BYTE *newbsl;  /* BSL just created */
  96.     long l, size;  /* l - index into BSL;  size - size of BSL in bytes */ 
  97.     long start;       /* where to start initializing entries to zeroes */
  98.     long nument();
  99.  
  100.     if (nents == 0) {    /* no VENDOR entries specified */
  101.         size = 512L;    /* default size of BSL to 1 sector */
  102.     } else {       /* num VENDOR entries is specified */
  103.         /*------------------------------------------------------*/
  104.         /* Calculate length of BSL in bytes.            */
  105.         /* Have to add space for reserved entries and USER list    */
  106.         /* (note: (+1) to round up)                */
  107.         /*------------------------------------------------------*/
  108.     size = (((nents + RENT + WARNBADSECTS)/EPS) + 1) * 512L;
  109.     }
  110.     
  111.     /* allocate enough memory for new BSL */
  112.     if ((newbsl = (BYTE *)mymalloc((int)size)) <= 0)
  113.         return err(nomemory);
  114.     
  115.     if (type == NEW) {    /* a new BSL */
  116.         start = 0;    /* start at 0th entry, i.e. init whole BSL to 0s */
  117.     }    
  118.     else {        /* expand the BSL */
  119.         /* start init to 0s after VENDOR list */
  120.     start = (nument(VENDOR) + RENT) * BPE;
  121.     
  122.         /* copy original BSL into this expanded memory */
  123.         for (l = 0; l < start; l++)
  124.             newbsl[l] = bsl[l];
  125.     }
  126.         
  127.             
  128.     /* free up old BSL */
  129.     if (bsl > 0) free(bsl);
  130.     bsl = newbsl;
  131.     
  132.     /* init BSL to zeroes beginning at 'start'th entry */
  133.     for (l = start; l < size; l++)
  134.         bsl[l] = 0;
  135.         
  136.     /* install BSL info */
  137.     bslsiz = size/512;    /* current num sectors BSL occupies */
  138.     put3bytes(bsl, nents);  /* num VENDOR entries */
  139.     mkmagic();    /* make the BSL checks sum to BSLMAGIC byte-wise */
  140.                           
  141.     return OK;
  142. }
  143.  
  144.  
  145. /*
  146.  *  Read the BSL into memory.
  147.  *    Input:
  148.  *        pdev - physical unit that contains the BSL.
  149.  *    Output:
  150.  *        bsl - pointer to the BSL.  (in bsl.h)
  151.  *    Return:
  152.  *        OK - everything is fine.
  153.  *        INVALID - BSL doesn't checksum correctly.
  154.  *        ERROR - can't read BSL.
  155.  */
  156. rdbsl(pdev)
  157. int pdev;    /* physical unit to read from */
  158. {
  159.     int ret;
  160.     
  161.     if ((ret = rdsects(pdev, (UWORD)bslsiz, bsl, (SECTOR)STBSL)) != 0) {
  162.         if (tsterr(ret) != OK) {
  163.             if (tformat == FALSE)
  164.             err(bslread);
  165.         }
  166.     return ERROR;
  167.     }
  168.         
  169.     return(sumbsl());    /* Checksum BSL and return */
  170. }
  171.  
  172.  
  173. /*
  174.  *  Count number of entries in the requested portion of BSL.
  175.  *    Input:
  176.  *        portion - portion of BSL.  MEDIA, VENDOR, USER or UNUSED.
  177.  *    Return:
  178.  *        Number of entries of the requested portion.
  179.  *    Comments:
  180.  *        There are 3 bytes per entry (BPE), and the first 2 entries
  181.  *    are reserved (RENT) for BSL info.
  182.  */
  183. long
  184. nument(portion)
  185. int portion;        /* portion of BSL to be counted */
  186. {
  187.     long  vdr, usr;        /* num ent in VENDOR list, num ent in USER list */
  188.     long  nbytes, offset;   /* BSL's len in bytes, index into BSL */
  189.     long  get3bytes();
  190.     
  191.     /* 2nd entry in BSL contains num entries in VENDOR list */
  192.     vdr = get3bytes(bsl);
  193.     
  194.     if (portion == VENDOR)  return (vdr);
  195.     
  196.     nbytes = bslsiz*512;    /* num bytes in BSL */
  197.     
  198.     /* num bytes available for valid entries */
  199.     /* (need this because nbytes may not be divisible by BPE) */
  200.     nbytes -= (nbytes % BPE);
  201.     
  202.     /* find out num entries in USER list */
  203.     usr = 0;
  204.     for (offset = (RENT+vdr)*BPE;  /* index into beginning of USER list */
  205.          (offset < nbytes)       /* while not at end of BSL */
  206.      && get3bytes(bsl+offset); /* and it's a used entry */
  207.          offset += BPE)           /* increment index */
  208.         usr++;        /* increment num entries for USER list */
  209.          
  210.     if (portion == USER)
  211.         return (usr);        /* num entries in USER list */
  212.         
  213.     if (portion == MEDIA)
  214.         return (vdr+usr);    /* num entries in MEDIA list */     
  215.         
  216.     /* portion == UNUSED */
  217.     return ((nbytes/BPE)-RENT-vdr-usr);
  218. }
  219.  
  220.  
  221. /*
  222.  *  Write the BSL into the disk.
  223.  *    Input:
  224.  *        pdev - physical unit number BSL belongs to.
  225.  *        bsl - pointer to buffer containing the BSL. (in bsl.h)
  226.  *    Return:
  227.  *        OK - everything is fine.
  228.  *        ERROR - can't write BSL.
  229.  */
  230. wrbsl(pdev)
  231. int pdev;    /* physical unit number */
  232. {
  233.     int ret;            /* return code */
  234.  
  235.     *((int *)(bsl + 0x4)) = 0;        /* set the 4th & 5th byte to 0 in BSL */
  236.     mkmagic();
  237.     if ((ret = wrsects(pdev, (UWORD)bslsiz, bsl, (SECTOR)STBSL)) != 0) {
  238.         if (tsterr(ret) != OK)
  239.             err(bslwrite);
  240.         return ERROR;
  241.     }
  242.  
  243.     return OK;
  244.  
  245.  
  246. /*
  247.  *  Sort the BSL in memory in ascending order.
  248.  *    Input:
  249.  *        entries - number of used entries in BSL
  250.  *        bsl - pointer to the BSL. (in bsl.h)
  251.  *    Output:
  252.  *        a sorted bsl.
  253.  *    Algorithm:
  254.  *        Bubble sort.
  255.  *    Comments:
  256.  *        The reserved entries won't be sorted.
  257.  */
  258. sortbsl(entries)
  259. long  entries;    /* num entries in BSL */
  260. {
  261.     long  i, e1, e2;
  262.     long  start;    /* beginning byte of entries in BSL */
  263.     long  end;        /* tail byte of BSL */
  264.     int   change;    /* signal if changes have been made in current pass */
  265.     long  get3bytes();
  266.     
  267.     if (entries == 0L || entries == 1L)    /* BSL is empty */
  268.         return;
  269.             
  270.     change = 1;        /* assume list is not in order */
  271.     start = RENT*BPE;    /* beginning of entries in BSL */
  272.     end = entries * BPE;
  273.     while (1) {
  274.         if (change == 0)    /* if no changes made, DONE --> HOME */
  275.         return;
  276.         
  277.         change = 0;    /* assume list is in order */
  278.         for (i = start; i <= end; i += BPE) {
  279.             e1 = get3bytes(bsl+i);
  280.             e2 = get3bytes(bsl+i+BPE);
  281.             if (e1 > e2) {            /* switch if out of order */
  282.                 put3bytes(bsl+i, e2);
  283.                 put3bytes(bsl+i+BPE, e1);
  284.                 change = 1;
  285.             }
  286.         }
  287.         end -= BPE;
  288.     }
  289. }
  290.  
  291.  
  292. /*
  293.  *  Search through a sorted BSL for a given sector number.
  294.  *    Input:
  295.  *        sect - sector number searching for.
  296.  *        entries - number of used entries in the BSL.
  297.  *    Return:
  298.  *        YES - if given sector is found.
  299.  *        NO - if given sector is not found.
  300.  *    Algorithm:
  301.  *        Binary Search.
  302.  */
  303. srchbsl(sect, entries)
  304. SECTOR  sect;    /* sector searching for */
  305. long  entries;    /* num used entries in BSL */
  306. {
  307.     long  start, mid, end; /* start, middle and end indices into list */
  308.     SECTOR  temp;       /* sector number in middle of list */
  309.     long  get3bytes();
  310.  
  311.     start = RENT;        /* start after reserved entries */
  312.     end = entries+RENT-1;    /* end of BSL */ 
  313.     
  314.     while (1) {
  315.          mid = (start + end) / 2;        /* middle entry in list */
  316.         temp = get3bytes(bsl+(mid*BPE));    /* sector num at mid entry */
  317.         
  318.         if (sect == temp)    /* given sector == sector at mid entry */
  319.             return YES;        /* given sector found in list */
  320.         else if (sect < temp)    /* given sector < sector at mid entry */
  321.             end = mid - 1;    /* limit search to smaller sector num */
  322.         else            /* given sector > sector at mid entry */
  323.             start = mid + 1;    /* limit search to larger sector num */
  324.             
  325.         if (end < start)    /* list is exhausted */
  326.             return NO;        /* can't find given sector */    
  327.     }
  328. }
  329.  
  330.  
  331. /*
  332.  *  Checksum (byte-wise) the BSL.
  333.  *    Input:
  334.  *        bsl - pointer to the BSL.  (in bsl.h)
  335.  *    Return:
  336.  *        OK - BSL checksum to BSLMAGIC (0xa5).
  337.  *        INVALID - BSL does not checksum to BSLMAGIC.
  338.  */
  339. sumbsl()
  340. {
  341.     register BYTE sum;    /* byte-wise sum of BSL */
  342.     long i;        /* index into BSL */
  343.     long length;    /* length of BSL in bytes */
  344.  
  345.     length = bslsiz*512;    /* length of entire BSL */
  346.     sum = 0;    /* initialize the sum */
  347.     
  348.     /* Sum up values in the BSL by byte */
  349.     for (i = 0; i < length; i++) {
  350.         sum += bsl[i];
  351.     }
  352.     if (sum != BSLMAGIC) {    /* doesn't checksum correctly */
  353.         return INVALID;
  354.     }
  355.     return OK;    /* checksum correctly */
  356. }
  357.  
  358.  
  359. /*
  360.  *  Make the BSL checks sum to BSLMAGIC.
  361.  */
  362. mkmagic()
  363. {
  364.     register BYTE diff;    /* difference to make BSL checks sum correctly */
  365.     long i;        /* index into BSL */
  366.     long len;        /* length of BSL in bytes */
  367.     
  368.     len = bslsiz*512;    /* length of entire BSl */
  369.     diff = BSLMAGIC;    /* initialize the difference */
  370.     
  371.     /* find out what number would make BSL checks sum to BSLMAGIC */
  372.     for (i = 0; i < len; i++) {
  373.         diff -= bsl[i];
  374.     }
  375.     
  376.     /* add that difference to checksum byte (1st byte of 2nd entry of BSL) */
  377.     bsl[BPE] += diff;
  378. }
  379.  
  380.  
  381. /*
  382.  *  Add bad sectors found to the Bad Sector List.
  383.  *    Input:
  384.  *        pdev - physical unit BSL belongs to.
  385.  *        portion - portion of BSL to add to.  VENDOR or USER.
  386.  *        nbad - number of bad sectors to be added.
  387.  *    Return:
  388.  *        toadd - number of new bad sectors added to the BSL.
  389.  *        USRFULL - user part of the BSL is filled up.
  390.  *        NOMEM - not enough memory for add buffer or BSL.
  391.  *        ERROR - something is wrong.
  392.  *    Comment:
  393.  *        The entry will be added only if it is not already on the
  394.  *    bad sector list.  Binary search is performed to guarantee this.
  395.  *        If the VENDOR list is full, this routine will take care
  396.  *    of the expansion of the list also.
  397.  */
  398. addbsl(pdev, portion, nbad) 
  399. int pdev;        /* physical unit number */
  400. int portion;        /* portion of BSL */
  401. int nbad;        /* num of bad sectors to be added */
  402. {
  403.     long  entries;    /* num entries to be retained in BSL */
  404.     long  empty;    /* num empty slots available for adding entries */
  405.     long  end;        /* address of end of BSL */
  406.     int  i, toadd;    /* index to badbuf, num of bad sectors to be added */
  407.     int  ret = 0;    /* return code */
  408.     SECTOR *addbuf;    /* bad sectors to be added to BSL */
  409.     long  nument();
  410.     
  411.     /* Allocate memory for sector numbers of bad sectors to be added */
  412.     if ((addbuf = (SECTOR *)mymalloc(nbad*4)) <= 0) {
  413.         err(nomemory);
  414.         return NOMEM;
  415.     }
  416.     
  417.     if (portion == VENDOR) {    /* adding to VENDOR list */
  418.         entries = nument(VENDOR);   /* only keep the VENDOR list */
  419.         empty = 0;            /* there's no unused slot for VENDOR ent */
  420.     } else {            /* adding to USER list */
  421.         entries = nument(MEDIA);    /* keep entire list */
  422.         empty = nument(UNUSED);     /* slots left unused */
  423.     }
  424.     sortbsl(entries);        /* sort BSL in ascending order */
  425.     toadd = 0;            /* none is to be added to BSL yet */
  426.  
  427.     /* For all bad sectors found, search for them in the current BSL.
  428.        Add them to the list only when they are not already recorded.  */    
  429.     if (entries) {    /* only search if BSL is not empty */
  430.     for (i = 0; i < nbad; i++) {
  431.         if (srchbsl(badbuf[i], entries) == NO) {
  432.         addbuf[toadd] = badbuf[i];
  433.         toadd++;
  434.         }
  435.         }
  436.     } else {  /* add in all bad sectors found */
  437.     for (i = 0; i < nbad; i++)
  438.         addbuf[i] = badbuf[i];
  439.         toadd = nbad;
  440.     }
  441.     
  442.     /* All bad sectors found have been recorded.  Nothing is added to BSL */
  443.     if (toadd == 0) {
  444.         if (portion == USER && (ret = rdbsl(pdev)) != OK) {
  445.             if (ret == INVALID)
  446.                 err(cruptbsl);
  447.         goto togo;
  448.     }
  449.         ret = toadd;
  450.     }
  451.     
  452.     /*------------------------------------------------------------------*/
  453.     /* Check if there are enough empty slots for new entries.  If not,    */
  454.     /* determine what kind of entries we are adding, VENDOR or USER.    */    
  455.     /* Expand the BSL if we are adding to VENDOR list.  Give warning    */
  456.     /* if we are adding to USER list.                          */
  457.     /*------------------------------------------------------------------*/
  458.     if (toadd > empty) {
  459.         if (portion == VENDOR) {    /* this only happens at format time */
  460.         /* expanded BSL should hold (entries + toadd) VENDOR entries */
  461.         if (creabsl(pdev, EXPAND, entries+toadd) != OK)
  462.             goto togo;
  463.         } else {            /* We are adding to USER list */
  464.             err(manybad);
  465.             toadd = empty;    /* num ent to add = empty slots available */
  466.         }
  467.     }
  468.     
  469.     /* Read in orig unsorted list if adding USER entries */
  470.     if (portion == USER) {
  471.         if ((ret = rdbsl(pdev)) != OK) {
  472.             if (ret == INVALID)
  473.                 err(cruptbsl);
  474.             goto togo;
  475.         }
  476.     }
  477.                 
  478.     /* Append new entries to end of BSL */
  479.     end = bsl + (RENT + entries)*BPE;    /* end of BSL */
  480.     for (i = 0; i < toadd; i++) {
  481.         put3bytes((end + i*BPE), addbuf[i]);
  482.     }
  483.     
  484.     /* make BSL checks sum to magic number */
  485.     mkmagic();
  486.  
  487.     if (portion == USER && toadd == empty) {
  488.         ret = USRFULL;
  489.         goto togo;
  490.     }
  491.         
  492.     ret = toadd;
  493.     
  494. togo:
  495.     if (addbuf > 0) free(addbuf);            
  496.     return(ret);
  497. }
  498.  
  499.  
  500. /*
  501.  *  Mark bad sectors from the BSL to FATs of a partition.
  502.  *    Input:
  503.  *        ldev - logical device the FATs belong to.
  504.  *        fat0 - logical sector number of where FAT 0 starts.
  505.  *        fatsiz - size of FAT in sectors.
  506.  *        data - logical sector number of where data clusters start.
  507.  *        portion - part of BSL to mark from.
  508.  */
  509. bsl2fat(ldev, fat0, fatsiz, data, portion)
  510. int  ldev;    /* logical device number */
  511. SECTOR fat0;    /* starting sector number (logical) of FAT 0 */ 
  512. UWORD fatsiz;    /* FAT size */
  513. SECTOR data;    /* starting sector number (logical) of data clusters */
  514. int portion;    /* part of BSL to mark from, VENDOR or MEDIA */
  515. {
  516.     long nument(), entries;    /* num entries in the list to be considered */
  517.     long i, end;        /* indices to the list to be considered */
  518.     long get3bytes();
  519.     SECTOR badsect;        /* a bad sector in the list */
  520.     SECTOR pstart;        /* phys sector num where partition starts */
  521.     SECTOR pdata;        /* phys sector num where data block starts */
  522.     SECTOR pend;        /* phys sector num where data block ends */
  523.     SECTOR logstart(), logend();
  524.     int nbad;
  525.     
  526.     nbad = 0;            /* assume none to be marked */
  527.     pstart = logstart(ldev);    /* find where partition starts */
  528.     pdata = pstart + data;    /* find where data block starts */
  529.     pend = logend(ldev);    /* find where data block ends */    
  530.     entries = nument(portion);    /* find num entries in given portion */
  531.     sortbsl(entries);        /* sort given portion of BSL */
  532.     
  533.     end = (RENT + entries) * BPE;
  534.     
  535.     /* Store vendor bad sectors of the logical device in badbuf */
  536.     for (i = BPE*RENT; i < end; i += BPE) {
  537.         if ((badsect = get3bytes(bsl+i)) > pend)
  538.             break;
  539.             
  540.         if (badsect >= pdata) {
  541.             badbuf[nbad++] = badsect;
  542.             
  543.             /* if badbuf overflows, mark what we have so far in the FAT */
  544.             if (nbad == WARNBADSECTS) {
  545.                 if (fixbadcls(ldev, fat0, fatsiz, data, nbad) < 0) {
  546.                     return ERROR;
  547.                 }
  548.                 nbad = 0;    /* reinit num bad sectors in partition to 0 */
  549.             }
  550.         }
  551.     }
  552.     
  553.     /* Bad sectors in partition not marked in FAT yet */
  554.     if (nbad) {
  555.         if (fixbadcls(ldev, fat0, fatsiz, data, nbad) < 0) {
  556.             return ERROR;
  557.         }
  558.     }
  559.     
  560.     return OK;
  561. }
  562.  
  563.  
  564. /*
  565.  *  Count number of bad sectors on a logical drive recorded in BSL.
  566.  *    Input:
  567.  *        ldev - logical drive to be considered.
  568.  *    Return:
  569.  *        nbad - number of bad sectors found.
  570.  */
  571. long
  572. cntbad(ldev)
  573. int  ldev;    /* logical drive number */
  574. {
  575.     SECTOR pstart, pend;    /* phys starting and ending block of ldev */
  576.     extern SECTOR logstart(), logend();
  577.     long nbad=0L;        /* num bad sectors on ldev */
  578.     long entries, nument(), bslend;
  579.     long curr, get3bytes();
  580.     int done, i;
  581.     
  582.     pstart = logstart(ldev);    /* starting block # of partition */
  583.     pend = logend(ldev);    /* ending block # of partition */
  584.     entries = nument(MEDIA);    /* num entries in BSL */
  585.     sortbsl(entries);        /* sort BSL */
  586.     
  587.     done = 0;
  588.     bslend = (RENT+entries) * BPE;
  589.     for (i = RENT*BPE; (!done) && (i < bslend); i += BPE) {
  590.         curr = get3bytes(bsl+i);  /* get next entry in BSL */
  591.         if (curr < pstart)      /* not within logical drive's range yet */
  592.             continue;
  593.         if (curr <= pend)      /* within logical drive's range */
  594.             nbad++;
  595.         else done = 1;          /* pass logical drive's range */
  596.     }
  597.     return (nbad);
  598. }
  599.  
  600.  
  601. /*
  602.  *  Put a word into memory in 68000 format.
  603.  *    Input:
  604.  *        p - pointer to memory.
  605.  *        i - word to be put.
  606.  */
  607. putword(p, i)
  608. BYTE *p;
  609. UWORD i;
  610. {
  611.     *p = i >> 8;
  612.     *(p+1) = i;
  613. }
  614.  
  615.  
  616. /*
  617.  *  Get a 68000 format word from memory.
  618.  *    Input:
  619.  *        p - pointer to memory.
  620.  *    Return:
  621.  *        i - word read from memory.
  622.  */        
  623. getword(p)
  624. BYTE *p;
  625. {
  626.     UWORD i=0x00ff, j=0x00ff;
  627.     
  628.     i &= *p;        /* first byte */
  629.     i <<= 8;
  630.     j &= *(p+1);    /* second byte */
  631.     i |= j;
  632.     return (i);
  633. }
  634.  
  635.  
  636. /*
  637.  *  Put 3 bytes (68000 format) into memory.
  638.  *    Input:
  639.  *        p - pointer to memory.
  640.  *        l - long which contains the 3 bytes at the low-bit end.
  641.  */
  642. put3bytes(p, l)
  643. BYTE *p;
  644. long l;
  645. {
  646.     *p = l >> 16;
  647.     *(p+1) = l >> 8;
  648.     *(p+2) = l;
  649. }    
  650.  
  651.  
  652. /*
  653.  *  Get 3 bytes (68000 format) from memory.
  654.  *    Input:
  655.  *        p - pointer to memory.
  656.  *    Return:
  657.  *        l - a long which contains the 3 bytes read in last 3 bytes.
  658.  */
  659. long
  660. get3bytes(p)
  661. BYTE *p;
  662. {
  663.     long  k=0x000000ff, l=0x000000ff;
  664.     
  665.     l &= *p;        /* first byte */
  666.     l <<= 16;
  667.     k &= *(p+1);    /* second byte */
  668.     k <<= 8;
  669.     l |= k;
  670.     k = 0x000000ff;
  671.     k &= *(p+2);    /* third byte */
  672.     l |= k;
  673.     return (l);
  674. }
  675.  
  676.  
  677.  
  678. /*
  679.  *  Get 4 bytes (68000 format) from memory.
  680.  *    Input:
  681.  *        p - pointer to memory.
  682.  *    Return:
  683.  *        l - a long which contains the 3 bytes read in last 3 bytes.
  684.  */
  685. long
  686. get4bytes(p)
  687. BYTE *p;
  688. {
  689.     long  k=0x000000ff, l=0x000000ff;
  690.     
  691.     l &= *p;        /* first byte */
  692.     l <<= 32;
  693.     k &= *(p+1);    /* second byte */
  694.     k <<= 16;
  695.     l |= k;
  696.     k = 0x000000ff;
  697.     k &= *(p+2);    /* third byte */
  698.     k <<= 8;
  699.     l |= k;
  700.     k = 0x000000ff;
  701.     k &= *(p+3);    /* Fourth byte */
  702.     l |= k;
  703.     return (l);
  704. }
  705.  
  706. /*
  707.  * Fixup bad sector entries in the FATs;
  708.  * suboptimal, since a FAT sector is read and two are
  709.  * written for EACH bad sector, even if there is
  710.  * more than one bad entry in a given FAT sector.
  711.  *
  712.  *
  713.  */
  714. fixbadcls(ldev, fat0, fatsiz, data, nbad)
  715. int ldev;        /* logical device */
  716. SECTOR fat0, data;
  717. UWORD fatsiz;
  718. int nbad;
  719. {
  720.     long numcl;
  721.     UWORD clno, nxtcl;
  722.     int i;
  723.     UWORD *buf;
  724.     SECTOR fat1;    /* physical starting sector# of 2nd FAT */
  725.     SECTOR pstart;    /* physical starting sector# of partition */
  726.     SECTOR badsect;    /* current bad sector */
  727.     extern SECTOR logstart();
  728.     extern LOGMAP logmap[];
  729.     int did=0, nmarked, ret, spc;
  730.     
  731.     
  732.     if((buf = (UWORD *)Malloc((long)fatsiz << 9)) <= 0)
  733.         return err(nomemory);
  734.     pstart = logstart(ldev);
  735.  
  736.     spc = 2*ratio;                    /* No, 2 spc */
  737.     numcl = (logmap[ldev-'C'].lm_siz - data) / spc;
  738.     fat1 = fat0 + fatsiz;
  739.             
  740.     if ((ret = rdsects(ldev, fatsiz, (char *)buf, fat0)) != 0) {
  741.         if (tsterr(ret) != OK)
  742.         err(fatread);
  743.     ret = ERROR;
  744.     goto fixend;
  745.     }
  746.     nmarked = 0;
  747.     for (i = 0; i < nbad; ++i) {
  748.     badsect = badbuf[i] - pstart;
  749.     if ((clno = (badsect - data)/spc) >= numcl)
  750.         continue;
  751.             
  752.        /* find out the next cluster number */
  753.        gw((UWORD *)(buf+clno+2), &nxtcl);
  754.             
  755.     /* Nope, ah ha, just mark it bad */
  756.     *(buf+clno+2) = 0xf7ff;    /* 0xfff7 in 8086-land */
  757.     nmarked++;
  758.  
  759.     /* write FAT0 and FAT1 */
  760.     if ((ret = wrsects(ldev, fatsiz, (char *)buf, fat0)) != 0 ||
  761.         (ret = wrsects(ldev, fatsiz, (char *)buf, fat1)) != 0)
  762.     {
  763.         if (tsterr(ret) != OK)
  764.             err(fatwrite);
  765.         ret = ERROR;
  766.         goto fixend;
  767.     }
  768.     }
  769.     ret = nmarked;
  770. fixend:
  771.     Mfree((long)buf);
  772.     return ret;
  773. }
  774.  
  775.